package ch3.Singleton;

import java.util.concurrent.atomic.AtomicLongFieldUpdater;

/**
 * 使用CAS实现线程安全的计数器
 * 使用CAS算法的代码模板：在循环体中读取共享变量V的旧值A，并以该值为输入经过一系列操作计算共享变量的新值B
 * 接着调用CAS试图将V的值更新为B；若更新失败则继续重试，直到成功。
 *
 * 注意：CAS只是保障了共享变量更新操作的原子性，但是并不能保障可见性
 * 所以需要用volatile来修饰共享变量count
 */

public class CASBasedCounter {
    private volatile long count;

    // 这里使用AtomicLongFieldUpdater便于讲解，实际使用中更多是用atomic包下的其他更为直接的类
    private final AtomicLongFieldUpdater<CASBasedCounter> fieldUpdater;

    public CASBasedCounter() {
        fieldUpdater = AtomicLongFieldUpdater.newUpdater(CASBasedCounter.class, "count");
    }

    public long value() {
        return count;
    }

    public void increment() {
        long oldValue;
        long newValue;

        do {
            oldValue = count;
            newValue = oldValue + 1;
        } while (compareAndSwap(oldValue, newValue));
    }

    private boolean compareAndSwap(long oldValue, long newValue) {
        boolean isOk = fieldUpdater.compareAndSet(this, oldValue, newValue);
        return isOk;
    }

}
